
enum FileOperationProgress
{
	FOP_PROGRESS_CONTINUE,FOP_PROGRESS_CANCEL
};

class WorkWatcher
{
public:
	virtual FileOperationProgress CurrentWork(LARGE_INTEGER currentWork) = 0;
	virtual void TotalWork(LARGE_INTEGER totalWork) = 0;
	virtual FileOperationProgress CurrentFile(const wxString &file) { return FOP_PROGRESS_CONTINUE; }
};

typedef boost::shared_ptr<WorkWatcher> WorkWatcherPtr;

enum FileOperationType
{
	FOP_COPY, FOP_DELETE, FOP_RENAME, FOP_MOVE
};

DWORD CALLBACK CopyProgressRoutine(LARGE_INTEGER TotalFileSize, LARGE_INTEGER TotalBytesTransferred, LARGE_INTEGER StreamSize, 
								   LARGE_INTEGER StreamBytesTransferred, DWORD dwStreamNumber, DWORD dwCallbackReason, HANDLE hSourceFile, 
								   HANDLE hDestinationFile, LPVOID lpData);
class FileOperationThread;

class FileOperation
{
public:
	friend DWORD CALLBACK CopyProgressRoutine(LARGE_INTEGER TotalFileSize, LARGE_INTEGER TotalBytesTransferred, LARGE_INTEGER StreamSize, 
											  LARGE_INTEGER StreamBytesTransferred, DWORD dwStreamNumber, DWORD dwCallbackReason, HANDLE hSourceFile, 
											  HANDLE hDestinationFile, LPVOID lpData);
	friend class FileOperationThread;

	FileOperation();
	void SetType(FileOperationType type);
	FileOperationType GetType();
	void AddDirectory(const wxString &directory);
	void AddFile(const wxString &file);
	void SetBasePath(const wxString &basePath);
	void SetDestinationPath(const wxString &destPath);
	wxString GetDestinationPath();
	wxArrayString &GetFileList();
	wxArrayString &GetDirectoryList();
	void SetWorkWatcher(WorkWatcherPtr workWatcher);
	void RegisterFilePropertiesWatcher(FilePropertiesWatcher *filePropertiesWatcher);
private:
	FileOperationType type;
	wxArrayString directories;
	wxArrayString files;
	wxString basePath;
	wxString destPath;

	FileTreeNodePtr root;
	LARGE_INTEGER totalFileSize;
	LARGE_INTEGER totalWork;
	LARGE_INTEGER currentProgress;	
	LARGE_INTEGER lastProgress;
	unsigned int numberOfFiles;
	WorkWatcherPtr workWatcher;
	vector<FilePropertiesWatcher *> filePropertiesWatchers;
};

class FileOperationManager
{
public:
	FileOperationManager();
	bool PerformOperation(const FileOperation &fop);	
	void AddTotalWork(LARGE_INTEGER work);
	void SubtractTotalWork(LARGE_INTEGER work);
	void AddCurrentWork(LARGE_INTEGER work);
	void SubtractCurrentWork(LARGE_INTEGER work);
	void RegisterWorkWatcher(WorkWatcher* watcher);
private:
	LARGE_INTEGER totalWork;
	LARGE_INTEGER currentWork;
	vector <WorkWatcher* > watchers;
};




class FileOperationThread : public wxThread
{
public:
	FileOperationThread(const FileOperation &pfop);
	FileOperationProgress PerfromOperation(FileTreeNodePtr root);
	virtual ExitCode Entry();	
	FileOperation &GetFileOperation();
private:
	FileOperationProgress PerfromMove(FileTreeNodePtr root);
	FileOperation fop;		
};